﻿using Cofe.Core.Interfaces;
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Cofe.Core.Service;
using Cofe.Core.EntryType;
using Cofe.Core.Utils;
using Cofe.Core.Dynamic;
using Cofe.Web;
using Cofe.Core.Property;
using Cofe.Core;
using System.Web.Routing;

namespace Cofe.Web
{
    public class CofeWSPropertyProvider : PropertyProviderBase<IPropertyHost>
    {
        #region Factory
        [Export(typeof(ICofeService))]
        [ServicePriority(ServicePriorityAttribute.DefaultPriority_COFEWS)]
        public class Factory : ISecondaryPropertyProviderFactory
        {
            public IEnumerable<IPropertyProvider> GetSecoondaryPropertyProviders(IPropertyHost propertyHost)
            {
                if (!(propertyHost.SecondaryPropertyProviders.Any((p) => p is CofeWSPropertyProvider)))
                    yield return new CofeWSPropertyProvider(propertyHost) { _sl = ServiceLocater };
            }

            private IServiceLocater _serviceLocater = null;
            public IServiceLocater ServiceLocater
            {
                get { return _serviceLocater ?? CofeServices.ServiceLocater; }
                set { _serviceLocater = value; }
            }

        }
        #endregion



        protected virtual IEnumerable<XmlLink> listLink(ParameterDic parameters)
        {
            string scheme = parameters.ContainsKey("Scheme") ? parameters["Scheme"] as string : 
                System.Web.HttpContext.Current.Request.Url.Scheme;
            string host = parameters.ContainsKey("Host") ? parameters["host"] as string :
                System.Web.HttpContext.Current.Request.Url.Host + ":" + System.Web.HttpContext.Current.Request.Url.Port;            

            Func<string, Uri> formatUri = (relPath) =>
                {
                    relPath = relPath.TrimStart('/');
                    if (String.IsNullOrEmpty(scheme)) throw new ArgumentNullException("Scheme");
                    if (String.IsNullOrEmpty(host)) throw new ArgumentNullException("Host");

                    return new Uri(String.Format("{0}://{1}/{2}", scheme, host, relPath));
                };

            string entryApiPath = "/api/entry";
            Guid entryId = Entity.Behaviors.GetProperty<Guid>(CacheProperties.Id);
            IEntryTypeInfo eti = Entity.Behaviors.GetProperty<IEntryTypeInfo>(CofeEntryTypeProperties.EntryTypeInfo);            

            yield return new XmlLink(MediaType.Entry, RelationType.Self, formatUri(String.Format("{0}/{1}", entryApiPath, entryId)));
            if (eti != null)
                yield return new XmlLink(MediaType.EntryType, RelationType.TypeInfo, formatUri(String.Format("{0}/{1}", entryApiPath, eti.Id)));

            foreach (var prop in Entity.Behaviors.GetSupportedProperties())
                if (DecoratorExtension.IsAction(prop) && DecoratorExtension.HasAlias(prop))
                    yield return new XmlLink(MediaType.Unknown, RelationType.Property, formatUri(String.Format("{0}/{1}", 
                        entryApiPath, DecoratorExtension.getAlias(prop).ToLower())));
        }


        #region Constructor

        private IServiceLocater _sl;
        private IEntryConstructor _ec { get { return _sl.FindService<IEntryConstructor>(); } }

        private IEntryTypeInfoManager _etim { get { return _sl.FindService<IEntryTypeInfoManager>(); } }

        public CofeWSPropertyProvider(IPropertyHost propertyHost)
            : base(propertyHost, Cofe.Core.PropertyDefinitions.CofeDefinitions)
        {
            registerAction<IEnumerable<XmlLink>>(CofeProperties.ListLinks,
                (pm) => listLink(pm));
        }

        #endregion
    }
}
